// Semaphore.cpp: implementation of the CSelfSemaphore class.
//
//////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "Semaphore.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////


CSelfSemaphore::CSelfSemaphore(int value,int timeout)
{
#ifdef WIN32
	m_sid = CreateSemaphore(NULL, value, value, NULL);
#elif defined(AIX) | defined(HP_UX)
	m_value = value;
	pthread_mutex_init(&m_mutex, NULL);
	pthread_cond_init(&m_cond,NULL);
#elif defined(LINUX)
	sem_init(&m_sid, 0, value);
#endif
	m_timeout=timeout;
}

CSelfSemaphore::~CSelfSemaphore()
{
#ifdef WIN32
	CloseHandle(m_sid);
#elif defined(AIX) | defined(HP_UX)
	pthread_cond_destroy(&m_cond);
	pthread_mutex_destroy(&m_mutex);
#elif defined(LINUX) 
	sem_destroy(&m_sid);
#endif
}


bool CSelfSemaphore::Lock()
{
#ifdef WIN32
	if (m_timeout==-1)
		return (WaitForSingleObject(m_sid, INFINITE)==WAIT_OBJECT_0);
	else
		return (WaitForSingleObject(m_sid, m_timeout*1000)==WAIT_OBJECT_0);
#elif defined(AIX)|defined(HP_UX)	
	pthread_mutex_lock(&m_mutex);
	while (m_value <= 0) 
	{
		if (m_timeout>0)
		{
        struct timeval timeout;
        gettimeofday(&timeout,0);
        struct timespec abstime;
        int over=m_timeout;
        abstime.tv_sec=timeout.tv_sec+m_timeout;
        abstime.tv_nsec=timeout.tv_usec;
				pthread_cond_timedwait(&m_cond,&m_mutex,&abstime);
				break;
		}
		else
		{
				pthread_cond_wait(&m_cond,&m_mutex);
		}
	}
	if(m_value > 0) {

		m_value--;
	}
	pthread_mutex_unlock(&m_mutex);
	return true;
#elif defined(LINUX)
	if (m_timeout>0)
	{
		struct timeval timeout;
		gettimeofday(&timeout,0);
		struct timespec abstime;
		int over=m_timeout;
		abstime.tv_sec=timeout.tv_sec+m_timeout;
		abstime.tv_nsec=timeout.tv_usec;
			return (sem_timedwait(&m_sid,&abstime)==0);
	}
	else
	{
		return (sem_wait(&m_sid) == 0);
	}
#endif
}


bool CSelfSemaphore::UnLock(int *pPrevCount)
{
#ifdef WIN32
	return (ReleaseSemaphore(m_sid, 1, (long *)pPrevCount) == TRUE);
#elif defined(AIX) | defined(HP_UX)	
	pthread_mutex_lock(&m_mutex);
	m_value++;
	pthread_cond_signal(&m_cond);111
	pthread_mutex_unlock(&m_mutex);
	if(pPrevCount != NULL){
		*pPrevCount = m_value;
	}
	return true;
#elif defined(LINUX)
	if(sem_post(&m_sid) == 0){
		if(pPrevCount != NULL)
		{
			sem_getvalue(&m_sid, pPrevCount);
		}
		return true;
	}
	return false;
#endif
}
